/*
 * 描          述:  <描述>
 * 修  改   人:  
 * 修改时间:  
 * <修改描述:>
 */
package com.tx.component.task.service.impl;

import java.beans.PropertyDescriptor;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.transaction.annotation.Transactional;

import com.tx.component.task.dao.TaskStatusDao;
import com.tx.component.task.model.TaskResultEnum;
import com.tx.component.task.model.TaskStatus;
import com.tx.component.task.model.TaskStatusEnum;
import com.tx.component.task.service.TaskStatusService;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.paged.model.PagedList;
import com.tx.core.querier.model.Querier;
import com.tx.core.querier.model.QuerierBuilder;

/**
 * TaskStatus的业务层
 * <功能详细描述>
 * 
 * @author  
 * @version  [版本号, ]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class TaskStatusServiceImpl implements TaskStatusService {
    
    @SuppressWarnings("unused")
    private Logger logger = LoggerFactory
            .getLogger(TaskStatusServiceImpl.class);
    
    private TaskStatusDao taskStatusDao;
    
    /** <默认构造函数> */
    public TaskStatusServiceImpl() {
        super();
    }
    
    /** <默认构造函数> */
    public TaskStatusServiceImpl(TaskStatusDao taskStatusDao) {
        super();
        this.taskStatusDao = taskStatusDao;
    }
    
    /**
     * @param taskId
     */
    @Override
    public void initByTaskId(String taskId, String signature) {
        AssertUtils.notEmpty(taskId, "taskId is empty.");
        AssertUtils.notEmpty(signature, "signature is empty.");
        
        Date now = new Date();
        TaskStatus taskStatus = findByTaskId(taskId);
        if (taskStatus == null) {
            taskStatus = new TaskStatus();
            taskStatus.setTaskId(taskId);
            taskStatus.setStatus(TaskStatusEnum.WAIT_EXECUTE);
            taskStatus.setResult(null);
            taskStatus.setCreateDate(now);
            taskStatus.setLastUpdateDate(now);
            
            //新增任务状态
            insert(taskStatus);
        } else {
            if (StringUtils.isEmpty(taskStatus.getSignature())) {
                //当任务签名为空时
                if (TaskStatusEnum.WAIT_EXECUTE
                        .equals(taskStatus.getStatus())) {
                    //如果任务签名为空，状态为待执行，则不用进行更新,
                    return;
                } else {
                    //如果签名为空，而状态非待执行，表示系统出现异常.此时应该抛出异常
                    AssertUtils.isTrue(
                            TaskStatusEnum.WAIT_EXECUTE
                                    .equals(taskStatus.getStatus()),
                            "taskId:{}.signature is empty.status should is 'WAIT_EXECUTE'.but status is :{}",
                            new Object[] { taskId, taskStatus.getStatus() });
                }
            } else if (!StringUtils.equals(signature,
                    taskStatus.getSignature())) {
                //签名不一致，不能进行修改
                return;
            } else if (StringUtils.equals(signature, taskStatus.getSignature())
                    && TaskStatusEnum.EXECUTING
                            .equals(taskStatus.getStatus())) {
                //当前容器刚启动，如果发现状态为执行中，则认为上一次待执行的任务结果为未完成，状态更新为待执行
                taskStatus.setStatus(TaskStatusEnum.WAIT_EXECUTE);
                taskStatus.setResult(TaskResultEnum.UNCOMPLETED);
                taskStatus.setEnd(now);
                taskStatus.setSignature(null);//将签名更新为空
                //更新任务状态
                updateById(taskStatus);
            }
        }
    }
    
    /**
     * @param taskStatus
     */
    @Override
    @Transactional
    public void insert(TaskStatus taskStatus) {
        //验证参数是否合法
        AssertUtils.notNull(taskStatus, "taskStatus is null.");
        AssertUtils.notEmpty(taskStatus.getTaskId(),
                "taskStatus.taskId is empty.");
        AssertUtils.notNull(taskStatus.getStatus(),
                "taskStatus.status is null.");
        
        //为添加的数据需要填入默认值的字段填入默认值
        Date now = new Date();
        taskStatus.setLastUpdateDate(now);
        taskStatus.setCreateDate(now);
        
        //调用数据持久层对实体进行持久化操作
        this.taskStatusDao.insert(taskStatus);
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean deleteById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        TaskStatus condition = new TaskStatus();
        condition.setId(id);
        int resInt = this.taskStatusDao.delete(condition);
        
        boolean flag = resInt > 0;
        return flag;
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    public TaskStatus findById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        TaskStatus condition = new TaskStatus();
        condition.setId(id);
        
        TaskStatus res = this.taskStatusDao.find(condition);
        return res;
    }
    
    /**
     * @param taskId
     * @return
     */
    @Override
    public TaskStatus findByTaskId(String taskId) {
        AssertUtils.notEmpty(taskId, "taskId is empty.");
        
        TaskStatus condition = new TaskStatus();
        condition.setTaskId(taskId);
        
        TaskStatus res = this.taskStatusDao.find(condition);
        return res;
    }
    
    /**
     * @param id
     * @return
     */
    @Override
    @Transactional
    public TaskStatus findWithLockById(String id) {
        AssertUtils.notEmpty(id, "id is empty.");
        
        TaskStatus condition = new TaskStatus();
        condition.setId(id);
        
        TaskStatus res = this.taskStatusDao.find(condition);
        return res;
    }
    
    /**
     * @param taskId
     * @return
     */
    @Override
    @Transactional
    public TaskStatus findWithLockByTaskId(String taskId) {
        AssertUtils.notEmpty(taskId, "taskId is empty.");
        
        TaskStatus condition = new TaskStatus();
        condition.setTaskId(taskId);
        
        TaskStatus res = this.taskStatusDao.findWithLock(condition);
        return res;
    }
    
    /**
     * @param params
     * @return
     */
    @Override
    public List<TaskStatus> queryList(Map<String, Object> params) {
        //判断条件合法性
        
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        List<TaskStatus> resList = this.taskStatusDao.queryList(params);
        
        return resList;
    }
    
    /**
     * @param querier
     * @return
     */
    @Override
    public List<TaskStatus> queryList(Querier querier) {
        //判断条件合法性
        
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        List<TaskStatus> resList = this.taskStatusDao.queryList(querier);
        
        return resList;
    }
    
    /**
     * @param params
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    public PagedList<TaskStatus> queryPagedList(Map<String, Object> params,
            int pageIndex, int pageSize) {
        //T判断条件合法性
        
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        PagedList<TaskStatus> resPagedList = this.taskStatusDao
                .queryPagedList(params, pageIndex, pageSize);
        
        return resPagedList;
    }
    
    /**
     * @param querier
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    public PagedList<TaskStatus> queryPagedList(Querier querier, int pageIndex,
            int pageSize) {
        //T判断条件合法性
        
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        PagedList<TaskStatus> resPagedList = this.taskStatusDao
                .queryPagedList(querier, pageIndex, pageSize);
        
        return resPagedList;
    }
    
    /**
     * @param params
     * @return
     */
    @Override
    public int count(Map<String, Object> params) {
        //判断条件合法性
        
        //生成查询条件
        params = params == null ? new HashMap<String, Object>() : params;
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        int res = this.taskStatusDao.count(params);
        
        return res;
    }
    
    /**
     * @param querier
     * @return
     */
    @Override
    public int count(Querier querier) {
        //生成查询条件
        querier = querier == null ? QuerierBuilder.newInstance().querier()
                : querier;
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        int res = this.taskStatusDao.count(querier);
        
        return res;
    }
    
    /**
     * @param key2valueMap
     * @param excludeId
     * @return
     */
    @Override
    public boolean exists(Map<String, String> key2valueMap, String excludeId) {
        AssertUtils.notEmpty(key2valueMap, "key2valueMap is empty");
        
        //生成查询条件
        Map<String, Object> params = new HashMap<String, Object>();
        params.putAll(key2valueMap);
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        int res = this.taskStatusDao.count(params, excludeId);
        
        return res > 0;
    }
    
    /**
     * @param querier
     * @param excludeId
     * @return
     */
    @Override
    public boolean exists(Querier querier, String excludeId) {
        AssertUtils.notNull(querier, "querier is null.");
        
        //根据实际情况，填入排序字段等条件，根据是否需要排序，选择调用dao内方法
        int res = this.taskStatusDao.count(querier, excludeId);
        
        return res > 0;
    }
    
    /**
     * @param id
     * @param updateRowMap
     * @return
     */
    @Override
    @Transactional
    public boolean updateById(String id, Map<String, Object> updateRowMap) {
        //验证参数是否合法，必填字段是否填写
        AssertUtils.notEmpty(id, "id is empty.");
        AssertUtils.notEmpty(updateRowMap, "updateRowMap is empty.");
        
        updateRowMap.put("lastUpdateDate", new Date());
        boolean flag = this.taskStatusDao.update(id, updateRowMap);
        //如果需要大于1时，抛出异常并回滚，需要在这里修改
        return flag;
    }
    
    /**
     * @param id
     * @param taskStatus
     * @return
     */
    @Override
    @Transactional
    public boolean updateById(String id, TaskStatus taskStatus) {
        //验证参数是否合法，必填字段是否填写
        AssertUtils.notNull(taskStatus, "taskStatus is null.");
        AssertUtils.notEmpty(id, "id is empty.");
        
        //生成需要更新字段的hashMap
        Map<String, Object> updateRowMap = new HashMap<String, Object>();
        //需要更新的字段
        //updateRowMap.put("taskId", taskStatus.getTaskId());
        updateRowMap.put("result", taskStatus.getResult());
        updateRowMap.put("status", taskStatus.getStatus());
        updateRowMap.put("nextFireDate", taskStatus.getNextFireDate());
        
        updateRowMap.put("start", taskStatus.getStart());
        updateRowMap.put("end", taskStatus.getEnd());
        updateRowMap.put("consuming", taskStatus.getConsuming());
        updateRowMap.put("executeCount", taskStatus.getExecuteCount());
        
        updateRowMap.put("failEnd", taskStatus.getFailEnd());
        updateRowMap.put("failCount", taskStatus.getFailCount());
        updateRowMap.put("failStart", taskStatus.getFailStart());
        updateRowMap.put("failConsuming", taskStatus.getFailConsuming());
        
        updateRowMap.put("successEnd", taskStatus.getSuccessEnd());
        updateRowMap.put("successCount", taskStatus.getSuccessCount());
        updateRowMap.put("successStart", taskStatus.getSuccessStart());
        updateRowMap.put("successConsuming", taskStatus.getSuccessConsuming());
        
        updateRowMap.put("signature", taskStatus.getSignature());
        updateRowMap.put("parameters", taskStatus.getParameters());
        updateRowMap.put("lastUpdateDate", new Date());
        
        boolean flag = this.taskStatusDao.update(id, updateRowMap);
        //如果需要大于1时，抛出异常并回滚，需要在这里修改
        return flag;
    }
    
    /**
     * @param taskStatus
     * @return
     */
    @Override
    @Transactional
    public boolean updateById(TaskStatus taskStatus) {
        //验证参数是否合法，必填字段是否填写
        AssertUtils.notNull(taskStatus, "taskStatus is null.");
        AssertUtils.notEmpty(taskStatus.getId(), "taskStatus.id is empty.");
        
        Map<String, Object> updateRowMap = new HashMap<String, Object>();
        BeanWrapper bw = PropertyAccessorFactory
                .forBeanPropertyAccess(taskStatus);
        for (PropertyDescriptor pd : bw.getPropertyDescriptors()) {
            if (pd.getWriteMethod() == null || pd.getReadMethod() == null) {
                continue;
            }
            if ("id".equals(pd.getName())) {
                continue;
            }
            TypeDescriptor td1 = bw.getPropertyTypeDescriptor(pd.getName());
            if (td1.hasAnnotation(Column.class)
                    && !td1.getAnnotation(Column.class).updatable()) {
                continue;
            }
            updateRowMap.put(pd.getName(), bw.getPropertyValue(pd.getName()));
        }
        updateRowMap.put("lastUpdateDate", new Date());
        boolean flag = updateById(taskStatus.getId(), updateRowMap);
        //如果需要大于1时，抛出异常并回滚，需要在这里修改
        return flag;
    }
    
    /**
     * @param 对taskStatusDao进行赋值
     */
    public void setTaskStatusDao(TaskStatusDao taskStatusDao) {
        this.taskStatusDao = taskStatusDao;
    }
}
